package fr.lelouet.monitoring.snapshot.receivers;

import java.io.File;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import fr.lelouet.monitoring.snapshot.DirectoryReader;
import fr.lelouet.monitoring.snapshot.HVSnapshot;
import fr.lelouet.monitoring.snapshot.SharedMainConfig;
import fr.lelouet.monitoring.snapshot.SnapshotReceiver;
import fr.lelouet.monitoring.snapshot.VMSnapshot;
import fr.lelouet.tools.regression.normalized.NormalizingSolver;
import fr.lelouet.tools.regression.normalized.RelativeResult;
import fr.lelouet.tools.sorters.MapSorter;

public class LinearModelizer implements SnapshotReceiver {

	private static final Logger logger = LoggerFactory
			.getLogger(LinearModelizer.class);

	private NormalizingSolver solver = null;

	@Override
	public void configure(Properties prop) {
	}

	@Override
	public void hypervisorModification(HVSnapshot toShow) {
		Map<String, Double> data = toShow.unfold();
		if (solver == null) {
			solver = new NormalizingSolver();
			solver.setDimensions(data.keySet().toArray(new String[] {}));
		}
		solver.addOrReduce(data, toShow.consumption);
	}

	@Override
	public void vmModification(VMSnapshot snapshot, HVSnapshot owner) {
		logger.debug("discarding vmsnapshot {}", snapshot);
	}

	void clear() {
		solver = null;
	}

	RelativeResult solve() {
		Set<String> uncompleteDimensions = solver.getUncompleteDimensions();
		logger.debug("discarding dimensions {}", uncompleteDimensions);
		solver.removeDimensions(uncompleteDimensions);
		return solver.solve();
	}

	public static void main(String[] args) {
		DirectoryReader reader = new DirectoryReader();
		LinearModelizer mod = new LinearModelizer();
		reader.register(mod);
		if (args.length == 0) {
			System.err.println("specify path with first arg");
			System.exit(1);
		}
		File argFile = new File(args[0]);
		if (!argFile.exists() || !argFile.isDirectory()) {
			argFile = null;
			File snapsResDir = new File(SharedMainConfig.snapshotsDir);
			if (snapsResDir.exists() && snapsResDir.isDirectory()) {
				argFile = new File(SharedMainConfig.snapshotsDir + "/"
						+ args[0]);
				if (!argFile.exists()) {
					System.err.println(argFile.getAbsolutePath()
							+ " does not exist");
					argFile = null;
				}
			}
			if (argFile == null) {
				System.err.println("cannot find dir " + args[0]
						+ " , neither in " + SharedMainConfig.snapshotsDir);
				System.exit(1);
			}
		}
		System.out.println("setting path to " + argFile.getAbsolutePath());
		reader.setDirPath(argFile.getAbsolutePath());
		reader.loadNewFiles();

		RelativeResult rr = mod.solve();
		System.out.println("estimates : " + rr.getEstimates());
		Map<String, Double> rweigths = rr.getRelativeWeights();
		List<String> sortedDims = MapSorter.sort(rweigths);
		LinkedHashMap<String, Double> orderedRelativeWeights = new LinkedHashMap<String, Double>();
		for (String s : sortedDims) {
			orderedRelativeWeights.put(s, rweigths.get(s));
		}
		System.out.println("relative weights ordered : "
				+ orderedRelativeWeights);
		System.out.println("errors : " + rr.getErrors());
	}

}
